using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using ZoneFiveSoftware.Common.Data;
using ZoneFiveSoftware.Common.Data.Fitness;
using FilteredStatistics.Common;

namespace FilteredStatistics.Data
{
    class TemplateNamedZone : INamedZone
    {
        public TemplateNamedZone(IActivity activity, Template template)
        {
            Template = template;
            Activity = activity;
        }

#region INamedZone members

        public String Name
        {
            get { return m_Template.Name; }
        }

        public IValueRangeSeries<DateTime> ValidTimes
        {
            get
            {
                RefreshCachedResult();

                return (ValueRangeSeries<DateTime>)m_ValidTimes;
            }
        }

        public event PropertyChangedEventHandler ValidTimesChanged;

#endregion

        void OnActivityPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            // Invalidate cache because something changed in the activity
            m_CachedInfoDirty = true;
        }

        void OnTemplatePropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            // Invalidate cache because something changed in the activity
            m_CachedInfoDirty = true;

            if(e.PropertyName == "FilterList")
            {
                // Be sure to unregister callbacks
                if (m_PreviousFilters != null)
                {
                    m_PreviousFilters.FilterListChanged -= new FilterList.FilterListChangedEventHandler(OnFilterListChanged);
                    m_PreviousFilters.FilterChanged -= new FilterList.FilterChangedEventHandler(OnFilterChanged);
                }

                if (Template.Filters != null)
                {
                    Template.Filters.FilterListChanged += new FilterList.FilterListChangedEventHandler(OnFilterListChanged);
                    Template.Filters.FilterChanged += new FilterList.FilterChangedEventHandler(OnFilterChanged);
                }

                m_PreviousFilters = Template.Filters;
            }

            TriggerValidTimesChanged();
        }

        void OnFilterChanged(Filter filter, PropertyChangedEventArgs changedProperty)
        {
            m_CachedInfoDirty = true;
            TriggerValidTimesChanged();
        }

        void OnFilterListChanged(FilterList filterList, PropertyChangedEventArgs changedProperty)
        {
            m_CachedInfoDirty = true;
            TriggerValidTimesChanged();
        }

        protected void TriggerValidTimesChanged()
        {
            if (ValidTimesChanged != null)
            {
                ValidTimesChanged(this, new PropertyChangedEventArgs("ValidTimes"));
            }
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            TemplateNamedZone namedZone = obj as TemplateNamedZone;

            if (namedZone != null)
            {
                return namedZone.Template == Template;
            }

            return base.Equals(obj);
        }

        private void RefreshCachedResult()
        {
            if (m_CachedInfoDirty)
            {
                m_CachedInfoDirty = false;

                m_ValidTimes.Clear();

                if (m_Template.Filters.Activity != null)
                {
                    m_ValidTimes = m_Template.Filters.GetMatchingRanges();
                }
            }
        }

        public IActivity Activity
        {
            get { return m_Activity; }
            set
            {
                if (Activity != value)
                {
                    if (Activity != null)
                    {
                        Activity.PropertyChanged -= new PropertyChangedEventHandler(OnActivityPropertyChanged);
                    }

                    m_Activity = value;
                    Template.Filters.Activity = value;

                    if (Activity != null)
                    {
                        Activity.PropertyChanged += new PropertyChangedEventHandler(OnActivityPropertyChanged);
                    }

                    m_CachedInfoDirty = true;
                }
            }
        }

        public Template Template
        {
            get { return m_Template; }
            set
            {
                if (Template != value)
                {
                    if (Template != null)
                    {
                        Template.PropertyChanged -= new PropertyChangedEventHandler(OnTemplatePropertyChanged);
                        Template.Filters.FilterListChanged -= new FilterList.FilterListChangedEventHandler(OnFilterListChanged);
                        Template.Filters.FilterChanged -= new FilterList.FilterChangedEventHandler(OnFilterChanged);
                    }

                    m_Template = value;
                    m_PreviousFilters = Template.Filters;

                    if (Template != null)
                    {
                        Template.PropertyChanged += new PropertyChangedEventHandler(OnTemplatePropertyChanged);
                        Template.Filters.FilterListChanged += new FilterList.FilterListChangedEventHandler(OnFilterListChanged);
                        Template.Filters.FilterChanged += new FilterList.FilterChangedEventHandler(OnFilterChanged);
                    }

                    m_CachedInfoDirty = true;
                }
            }
        }

        private Template m_Template = null;
        private IActivity m_Activity = null;
		private FilterResults m_ValidTimes = new FilterResults();
        private FilterList m_PreviousFilters = null;
        private bool m_CachedInfoDirty = true;
    }
}
